package bancosys.tec.rtm.diagnostician.report.text;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.LogFactory;

import bancosys.tec.rtm.diagnostician.DiagnosisBean;
import bancosys.tec.rtm.diagnostician.report.DiagnosticianReportGenerator;

/**
 * Implementação do gerador de relatórios de diagnostico em formato texto.
 * 
 * @author Evaristo
 * @version $Id:$ <b>Created on: </b> 23/01/2007
 */
public class DiagnosticianReportGeneratorText implements DiagnosticianReportGenerator {
    private final String encoding;

    /**
     * C'tor
     * 
     * @param encoding the encoding to use in the text
     */
    public DiagnosticianReportGeneratorText(String encoding) {
        super();
        this.encoding = encoding;
    }

    /**
     * C'tor that uses the default charset
     */
    public DiagnosticianReportGeneratorText() {
        this(Charset.defaultCharset().name());
    }

    /**
     * Gera e escreve um relatório dos diagnósticos no objeto OutputStream que é passado como parametro em modo texto.
     * 
     * @param outputStream OutputStream
     * @param diagnosticians List
     */
    public void generateReport(OutputStream outputStream, List<DiagnosisBean> diagnosticians) {
        PrintWriter printWriter = new PrintWriter(this.createWriter(outputStream));

        printWriter.println("Relatório do Diagnosticador");
        printWriter.println();
        printWriter.println("  Número de Itens Diagnosticados: " + diagnosticians.size());
        printWriter.println("  Data Hora do Diagnóstico: " + this.formatDate(new Date()));
        printWriter.println("  Rede: ");
        for (String ethAddresses : this.getHostIPs()) {
            printWriter.println("        " + ethAddresses);
        }

        if (diagnosticians.size() > 0) {
            printWriter.println();
            printWriter.println("  Itens Diagnosticados: ");
            Iterator<DiagnosisBean> diagnosticiansIterator = diagnosticians.iterator();
            while (diagnosticiansIterator.hasNext()) {
                printWriter.println("-----------------------------------------------------------------------------");
                DiagnosisBean diagnosisBean = diagnosticiansIterator.next();
                printWriter.println();
                printWriter.println("    Item Diagnosticado: " + diagnosisBean.getDiagnosticianName());
                printWriter.print("    Status: ");
                if (diagnosisBean.isWorking()) {
                    printWriter.print("ATIVO");
                } else {
                    printWriter.print("DESATIVADO");
                }
                printWriter.println();
                printWriter.println();
                if (diagnosisBean.getDescriptions().size() > 0) {
                    printWriter.println("    Evidencias:");
                    Iterator<String> descriptionsIterator = diagnosisBean.getDescriptions().iterator();
                    while (descriptionsIterator.hasNext()) {
                        String obj = descriptionsIterator.next();
                        if (obj != null) {
                            printWriter.println();
                            printWriter.print("      - " + obj);
                        }
                    }
                    printWriter.println();
                }
            }
            printWriter.println();
            printWriter.println("-----------------------------------------------------------------------------");
            printWriter.flush();
        }
    }

    /**
     * Wraps the {@link OutputStream} into a {@link Writer} using the {@link #encoding} passed in the constructor. Falls back to the current
     * default charset if it was not available
     * 
     * @param out {@link OutputStream}
     * @return {@link Writer}
     */
    private Writer createWriter(OutputStream out) {
        try {
            return new OutputStreamWriter(out, this.encoding);
        } catch (UnsupportedEncodingException e) {
            LogFactory.getLog(DiagnosticianReportGeneratorText.class).warn("unsupported encoding", e);
            return new OutputStreamWriter(out);
        }
    }

    /**
     * Formata uma data.
     * 
     * @param date data.
     * @return representacao da data em string.
     */
    private String formatDate(Date date) {
        return new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(date);
    }

    /**
     * @return os endereços do host, por adaptadores de rede
     */
    private List<String> getHostIPs() {
        List<String> ips = new ArrayList<String>();
        Enumeration<NetworkInterface> interfaces;
        try {
            interfaces = NetworkInterface.getNetworkInterfaces();
        } catch (Exception e) {
            // Não conseguiu encontrar interfaces de rede
            return ips;
        }

        while (interfaces.hasMoreElements()) {
            NetworkInterface eth = interfaces.nextElement();
            // Não quero o endereço de loopback
            if (eth == null || "lo".equals(eth.getName())) {
                continue;
            }
            StringBuilder line = new StringBuilder();
            line.append(eth.getName() + ": ");

            Enumeration<InetAddress> inets;
            try {
                inets = eth.getInetAddresses();
            } catch (Exception e) {
                // Não conseguiu encontrar endereços para a interface
                continue;
            }
            while (inets.hasMoreElements()) {
                InetAddress inet = inets.nextElement();
                if (inet != null) {
                    line.append(inet.getHostAddress() + "  ");
                }
            }
            ips.add(line.toString());
        }
        return ips;
    }
}